package server.loader;

import server.*;
import server.util.LifecycleSupport;


public class WebappLoader implements Loader, Lifecycle, Runnable {

    private Thread thread = null;
    //是否关闭线程
    private boolean threadDone = false;
    private String threadName = "WebappLoader";


    private static final String info =
            "server.loader.WebappLoader/1.0";
    //关联的容器
    private Container container = null;
    //类加载器
    private WebappClassLoader classLoader = null;
    //检查文件修改时间间隔(以秒为单位)
    private int checkInterval = 1;
    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
    //是否支持重载
    private boolean reloadable = false;
    private boolean started = false;
    private int debug = 0;

    private void log(String message) {
        Logger logger = null;
        if (container != null)
            logger = container.getLogger();
        if (logger != null)
            logger.log("WebappLoader[" + container.getName() + "]: " + message);
        else {
            String containerName = null;
            if (container != null)
                containerName = container.getName();
            System.out.println("WebappLoader[" + containerName + "]: " + message);
        }
    }

    private void log(String message, Throwable throwable) {
        Logger logger = null;
        if (container != null)
            logger = container.getLogger();
        if (logger != null) {
            logger.log("WebappLoader[" + container.getName() + "] " + message, throwable);
        } else {
            String containerName = null;
            if (container != null)
                containerName = container.getName();
            System.out.println("WebappLoader[" + containerName + "]: " + message);
            System.out.println("" + throwable);
            throwable.printStackTrace(System.out);
        }
    }

    public int getCheckInterval() {
        return checkInterval;
    }

    public void setCheckInterval(int checkInterval) {
        this.checkInterval = checkInterval;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer("WebappLoader[");
        if (container != null)
            sb.append(container.getName());
        sb.append("]");
        return sb.toString();
    }



    //实现Loader接口-----------------------------------------------------------------------------------
    @Override
    public Container getContainer() {
        return container;
    }

    @Override
    public void setContainer(Container container) {
        this.container = container;
        if (container != null && container instanceof Context) {
            setReloadable(((Context)container).getReloadable());
        }
    }

    @Override
    public WebappClassLoader getClassLoader() {
        return classLoader;
    }

    @Override
    public boolean getReloadable() {
        return reloadable;
    }

    @Override
    public void setReloadable(boolean reloadable) {
        boolean oldReloadable = this.reloadable;
        this.reloadable = reloadable;
        if (!started)
            return;
        //修改为支持重载,开启线程扫描
        if (!oldReloadable && reloadable) {
            threadStart();
        } else if (oldReloadable && !reloadable) {
            //修改为不支持重载,关闭线程
            threadStop();
        }
    }

    @Override
    public boolean modified() {
        return classLoader.modified();
    }

    @Override
    public String getInfo() {
        return info;
    }

    //实现Lifecycle接口---------------------------------------------------------------------------------
    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }

    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }

    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    @Override
    public void start() throws LifecycleException {
        if (started)
            throw new LifecycleException("Loader has already been started");
        if (debug >= 1)
            log("Starting this Loader");
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;
        if (container == null || !(container instanceof Context))
            return;
        classLoader = new WebappClassLoader(container.getName());
        if (classLoader instanceof Lifecycle)
            ((Lifecycle) classLoader).start();

        if (reloadable) {
            log("Reloading checks are enabled for this Context");
            try {
                threadStart();
            } catch (IllegalStateException e) {
                throw new LifecycleException(e);
            }
        }
    }

    @Override
    public void stop() throws LifecycleException {
        if (!started)
            throw new LifecycleException("Loader has not yet been started");
        if (debug >= 1)
            log("Stopping this Loader");
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
        if (reloadable)
            threadStop();
        if (classLoader instanceof Lifecycle)
            ((Lifecycle) classLoader).stop();
        classLoader = null;

    }

    private void threadStart() {
        //已经启动过线程
        if (thread != null || !reloadable)
            return;
        if (debug >= 1)
            log(" 启动支持热部署线程");
        threadDone = false;
        threadName = "WebappLoader[" + container.getName() + "]";
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.start();
    }

    private void threadStop() {
        if (thread == null)
            return;
        if (debug >= 1)
            log("  关闭支持热部署线程");
        threadDone = true;
        thread.interrupt();
        try {
            thread.join();
        } catch (InterruptedException e) {
            ;
        }
        thread = null;
    }



    //实现Runnable接口-----------------------------------------------------------------------------------

    @Override
    public void run() {
        while (!threadDone) {
            threadSleep();
            if (!started)
                break;
            try {
                if (!classLoader.modified())
                    continue;
            } catch (Exception e) {
                log("Error tracking modifications");
                continue;
            }
            //需要重新加载
            new Thread(new Runnable() {
                @Override
                public void run() {
                    ((Context)container).reload();
                }
            }).start();
            break;
        }
    }

    //线程睡眠一段时间
    private void threadSleep() {
        try {
            Thread.sleep(checkInterval * 1000L);
        } catch (InterruptedException e) {
            ;
        }
    }


}
